/**
 * 关于模块
 * 一、模块的定义
 *    a.主要有三种方式：内联、同目录下同名文件、同名文件下下的mod.rs
 *    b.在rust,从模块、函数（方法）、类型、类型成员，都有pub,private属性。
 *    默认是private,只能在当前文件内访问。
 *    比较让人差异的是结构体就算是pub类型的，但是如果它的成员是private的，那么也是无法定义一个
 *    结构体的实例。
 *    c.模块可以包含子模块，可以一直嵌套下去
 * 二、模块的引入
 *    a. 导入单个对象，无别名  - use 模块名::子模块::方法名/对象; 
 *    b. 导入单个对象且用别名  - use 模块名::子模块::方法名/对象 as 别名;
 *    c. 导入多个对象         - use 模块名::子模块::{对象1,对象2,....};
 *    d. 导入模块下所有对象    - use 模块名::子模块::*;  
 * 三、使用外部单元包
 *    a.通常是cargo install 包名,之后会在Cargo.toml中自动生成依赖项
 *    b.使用use语句引入即可
 *    c.如果你不找到这个单元包有什么东西，可以使用cargo doc --open查看
 *      也许以后，可以直接在ide中查看外部包的结构，就好像eclipse,idea查看java外部包一样
 * 四、一个文件中不同模块之间的访问
 *    假设一个文件内有a,b,c三个模块,那么:
 *    a.各个模块内对方访问其它模块对象没有特别简洁的方法，只能使用:
 *       super::其它模块名::对象
 *       例如a.f1访问b.f2,那么必须在a.f1中写super::b::f2
 *    b.虽然a,b,c都属于一个模块的多个子模块块，但是它们也只能看到对方的公共成员
 */
mod teacher;
mod student;

//模块引入，都引入为公共模块
//extern crate lzfmath; 
//use crate::student::student_info::stru_student;   //通常不要那么麻烦，还要加crate
//use student::student_info::stru_student;  //引入单个
use student::student_info::*;  //引入所有的，不要那么麻烦
use student::student_course::Course as Subject;  //引入单个且用别名
use lzfmath::{Point,Tpoint};

struct Programmer{
    name:String,
    age:i32,
    sex:String
}

pub trait Work{ 
    fn design(&self);
    fn code(&self);
    fn test(&self);
}

pub trait Tpoints{
    fn get_x(&self) -> u64;
    fn get_y(&self) -> u64;
    fn add(&self ,p:&Point)-> Point;
}
impl Tpoints for Point{
    fn get_x(&self)-> u64 {
       self.x
    }
    fn get_y(&self) -> u64 {
        self.y
    }
    fn add(&self ,p:&Point)-> Point {
       Point{
        x:self.x+p.x,
        y:self.y+p.y,
       }
    }
}
// 如能实现Tpoint,是因为Tpoint是其它单元包的内容
// impl Tpoint for Point{
//     fn get_x(&self)-> u64 {
//        self.x
//     }
//     fn get_y(&self) -> u64 {
//         self.y
//     }
//     fn add(&self ,p:&Point)-> Point {
//        Point{
//         x:self.x+p.x,
//         y:self.y+p.y,
//        }
//     }
// }

fn main() {
    teacher::go();    
    student::go();

    //直接使用子模块的子模块方法
    teacher::teacher_common::teach();
    let stu=stru_student{
        name:"tom".to_string(),
        sex:"男".to_string(),
        age:12,
    };

    print_student(stu);

    let sub=Subject::汉语;
    print!("{:?}",sub);
    teacher::stduy_hard();

    let pro=Programmer{
        name:"tom".to_string(),
        age:12,
        sex:"男".to_string()
    };
    pro.design();

    //使用另外一个库的内容

}
